#include <controller/TLSController.h>
#include <localview/LocalView.h>
#include <controller/TimeIncrementCalculationStrategy.h>
#include <evolutive/TimeIncrementEvolutiveStrategy.h>
#include <controller/Case.h>
#include <log.h>

const std::string TLSController::TAG = "TLSController";

TLSController::TLSController(const char* name, int x, int y) {
	mControllerId = std::string(name);

	mLocalView = new LocalView(std::string(name), x, y);

	rsi::log("TLSController", __FILE__, __LINE__, "Created a new controller %s", name);
}

TLSController::~TLSController() {
}

void TLSController::addStreet(const char* name, int direction) {
	std::string streetName = std::string(name);
	Node* localNode = mLocalView->getNetwork();

	//Setup local address to make local node complaint with interface used by all nodes
	//TODO define address format and a constant to represent local address

	Street* street = new Street(streetName, direction);

	localNode->addStreet(street);
}

void TLSController::updateStreetSensors(const char* name, int flush, int queueSize) {
	std::string streetName = std::string(name);
	Street* street = mLocalView->getNetwork()->getStreetByName(streetName);

	//TODO include fuzzification rules
	street->setFlush(flush%5);
	street->setQueue(queueSize%5);
}

void TLSController::addNeighbor(const char* address, const char* streetName, const char* id, int direction, int x, int y) {
	std::string streetname = std::string(streetName);
	std::string nodeId = std::string(id);

	//Create a new Node object to represent this new neighbors
	Node* neighborNode = new Node(nodeId);

	//Add to this neighbor the name of street that links together this neighbor to the local node.
	//This street will store data received from neighbor
	Street* street = new Street(streetName, direction);

	neighborNode->addStreet(street);

	mLocalView->getNetwork()->addNeighbor(neighborNode, direction);
}

void TLSController::startPhaseIncrementCalc(int phaseId) {
	rsi::log(TAG, __FILE__, __LINE__, "Starting Increment Calculation to tls: %s, phase: %d", mControllerId.c_str(), phaseId);

	TimeIncrementCalculationStrategy* strategy = new TimeIncrementEvolutiveStrategy();

	registerBackgroundCalcTask(strategy, phaseId);

	strategy->start(mLocalView, phaseId);
}

int TLSController::getPhaseIncrement(int phaseId) {

	if(mActiveCalc.find(phaseId) == mActiveCalc.end()) {
		return 0;
	}

	TimeIncrementCalculationStrategy* strategy = mActiveCalc[phaseId];
	strategy->stop();

	Case* c = strategy->getResult();

	int extension = c->getLocalGreenExtension();

	unregisterBackgroundCalcTask(phaseId);

	return extension;
}

void TLSController::registerBackgroundCalcTask(TimeIncrementCalculationStrategy* tics, int phaseId) {
	mActiveCalc[phaseId] = tics;
}

TimeIncrementCalculationStrategy* TLSController::unregisterBackgroundCalcTask(int phaseId) {
	mActiveCalc.erase(phaseId);
}
